#include "ai_common.h"
#include <vector>
#include <iostream>


/* ---------- FFD 算法（输入为 pair 向量） ----------- */
std::vector<Bin> first_fit_decreasing(std::vector<std::pair<int,int>> sorted_elems) {
    /* 1. 按 value 降序，value 相等时按 idx 升序 */

    /* 2. 依次放入桶 */
    std::vector<Bin> bins;
    for (const auto& it : sorted_elems) {
        bool placed = false;
        for (auto& b : bins) {
            if (b.try_put(it)) {
                placed = true;
                break;
            }
        }
        if (!placed) {                 // 3. 放不下 → 新建桶
            bins.push_back(Bin{{it}, it.second});
        }
    }
    return bins;
}


void check_folder(const char *folder_path) {
    assert(folder_path != NULL && "Folder path must not be NULL");
    // 检查文件夹是否存在
    if (access(folder_path, F_OK) != 0) {
        printf("Folder '%s' does not exist.\n", folder_path);
        if (fs::create_directories(folder_path))
        {
            printf("fs create dir succ: %s \n", folder_path);
        }
    } else {
        // printf("Folder '%s' exists.\n", folder_path);
    }
}

template <typename T>
bool write_bin_file(const char *filename, T *buffer, size_t size) {
    FILE *file = fopen(filename, "wb"); // 打开文件，以二进制写入方式打开    
    if (file != NULL) {        
        fwrite(buffer, sizeof(T), size, file); // 将数据写入文件        
        fclose(file); // 关闭文件    
        return true;
    } else {
        return false;
    }
}
template bool write_bin_file<uint64_t>(const char *filename, uint64_t *buffer, size_t size);
template bool write_bin_file<int8_t>(const char *filename, int8_t *buffer, size_t size);
template bool write_bin_file<uint32_t>(const char *filename, uint32_t *buffer, size_t size);
// 从二进制文件中读取数据到缓冲区
template <typename T>
bool read_bin_file(const char *filename, T *buffer, size_t size) {
    FILE *file = fopen(filename, "rb");  // 以二进制读取模式打开文件
    if (file == NULL) {
        // 文件打开失败
        return false;
    }

    // 读取数据
    size_t elementsRead = fread(buffer, sizeof(T), size, file);
    fclose(file);  // 关闭文件

    if (elementsRead != size) {
        // 读取的元素数量与期望的数量不一致，可能读取失败
        return false;
    }

    return true;
}

template bool read_bin_file<uint32_t>(const char *filename, uint32_t *buffer, size_t size);
template bool read_bin_file<uint64_t>(const char *filename, uint64_t *buffer, size_t size);



// 从二进制文件中读取数据到缓冲区
template <typename T>
size_t read_bin_file(const char *filename, T *buffer) {
    // 以二进制读取模式打开文件
    FILE* file = fopen(filename, "rb");
    if (file == nullptr) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return 0;
    }

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 计算元素数量
    size_t numElements = fileSize / sizeof(T);
    if (numElements == 0) {
        std::cerr << "文件为空或无法读取: " << filename << std::endl;
        fclose(file);
        return 0;
    }
    // 读取数据
    size_t elementsRead = fread(buffer, sizeof(T), numElements, file);
    if (elementsRead != numElements) {
        std::cerr << "读取文件时出错: " << filename << std::endl;
        fclose(file);
        return 0;
    }

    // 关闭文件
    fclose(file);
    return numElements;
}
// 显式实例化 uint64_t 类型
template size_t read_bin_file<uint64_t>(const char *filename, uint64_t *buffer);
template size_t read_bin_file<uint32_t>(const char *filename, uint32_t *buffer);

template <typename T>
bool exportVecToBin(const std::vector<T>& data, const char* filename) {
    // 以二进制写入模式打开文件
    FILE* file = fopen(filename, "wb");
    if (file == nullptr) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return false;
    }

    // 写入数据
    size_t elementsWritten = fwrite(data.data(), sizeof(T), data.size(), file);
    if (elementsWritten != data.size()) {
        std::cerr << "写入文件时出错: " << filename << std::endl;
        fclose(file);
        return false;
    }

    // 关闭文件
    fclose(file);
    return true;
}
// 显式实例化 uint16_t 类型
template bool exportVecToBin<uint32_t>(const std::vector<uint32_t>& data, const char* filename);

// 从二进制文件读取数据到 std::vector<T>
template <typename T>
size_t readBinToVec(std::vector<T>& data, const char* filename) {
    // 以二进制读取模式打开文件
    FILE* file = fopen(filename, "rb");
    if (file == nullptr) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return 0;
    }

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 计算元素数量
    size_t numElements = fileSize / sizeof(T);
    data.resize(numElements);

    // 读取数据
    size_t elementsRead = fread(data.data(), sizeof(T), numElements, file);
    if (elementsRead != numElements) {
        std::cerr << "读取文件时出错: " << filename << std::endl;
        fclose(file);
        return 0;
    }

    // 关闭文件
    fclose(file);
    return numElements;
}

template <typename T>
size_t readBinToVec(std::vector<T>& data, std::string filename) {
    // 以二进制读取模式打开文件
    FILE* file = fopen(filename.c_str(), "rb");
    if (file == nullptr) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return 0;
    }

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 计算元素数量
    size_t numElements = fileSize / sizeof(T);
    data.resize(numElements);

    // 读取数据
    size_t elementsRead = fread(data.data(), sizeof(T), numElements, file);
    if (elementsRead != numElements) {
        std::cerr << "读取文件时出错: " << filename << std::endl;
        fclose(file);
        return 0;
    }

    // 关闭文件
    fclose(file);
    return numElements;
}

template size_t readBinToVec<uint32_t>(std::vector<uint32_t>& data, const char* filename);
template size_t readBinToVec<uint64_t>(std::vector<uint64_t>& data, const char* filename);
template size_t readBinToVec<float>(std::vector<float>& data, const char* filename);
template size_t readBinToVec<uint64_t>(std::vector<uint64_t>& data, std::string filename);
template size_t readBinToVec<float>(std::vector<float>& data, std::string filename);


